package com.ljh.localmusic.ui

import android.annotation.SuppressLint
import android.net.Uri
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import com.ljh.localmusic.data.local.AppCache
import com.ljh.localmusic.data.local.UriTypeAdapter
import com.ljh.localmusic.data.local.models.AudioItem
import com.ljh.localmusic.data.repository.MusicRepository
import com.ljh.localmusic.foundation.media_player.MusicServiceHandler
import com.ljh.localmusic.runtime.App
import com.ljh.localmusic.runtime.GenerateImageUsecase
import com.ljh.localmusic.ui.model.ImageUrlModel
import com.ljh.localmusic.utils.MediaStateEvents
import com.ljh.localmusic.utils.MusicStates
import com.ljh.localmusic.R
import com.ljh.localmusic.utils.ext.logd
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import java.util.concurrent.TimeUnit.MILLISECONDS
import java.util.concurrent.TimeUnit.MINUTES
import java.util.concurrent.TimeUnit.SECONDS
import javax.inject.Inject

/**
 * author：LJH on 2025/8/16 10:29
 *
 */
@HiltViewModel
class HomeViewModel @Inject constructor(
    private val musicRepository: MusicRepository,
    private val musicServiceHandler: MusicServiceHandler,
    private val generateImageUsecase: GenerateImageUsecase
) : ViewModel(){

    private val _musicListState = MutableStateFlow<List<AudioItem>>(emptyList())
    val musicListState = _musicListState.asStateFlow()

    private val _imageModel = MutableStateFlow(ImageUrlModel())
    val imageModel = _imageModel.asStateFlow()

    // 播放器状态
    val musicStates = musicServiceHandler.musicStates

    private val _isPlaying = MutableStateFlow(false)
    val isPlaying = _isPlaying.asStateFlow()

    private val _isDataLoading = MutableStateFlow(false)
    val isDataLoading = _isDataLoading.asStateFlow()

    private val _currentPosition = MutableStateFlow(0L)
    val currentPosition = _currentPosition.asStateFlow()

    private val _toastMsg = MutableStateFlow("")
    val toastMsg = _toastMsg.asStateFlow()

    private val _autoNext = MutableStateFlow(0L)
    val autoNext = _autoNext.asStateFlow()


    private val _mediaItemIndex = MutableStateFlow(musicServiceHandler.currentItemIndex())
    val mediaItemIndex = _mediaItemIndex.asStateFlow()

    private val gson by lazy {
        GsonBuilder()
            .registerTypeAdapter(Uri::class.java, UriTypeAdapter()) // 关键：注册适配器
            .create()
    }

    init {
        if (imageModel.value.url.isEmpty()){
            refreshAiImage()
        }

        viewModelScope.launch{
            musicStates.collect{
//                "musicState Change: ${it}".logd()
                when(it){
                    is MusicStates.MediaPlaying -> {
                        _isPlaying.value = it.isPlaying
                    }
                    is MusicStates.MediaProgress -> {
                        _currentPosition.value = it.progress
                    }
                    is MusicStates.AutoChangeMediaItem -> {
                        "当前索引：${currentPosition.value},it.mediaItemIndex:${it.mediaItemIndex}".logd()
                        _autoNext.value = System.currentTimeMillis()
                        _currentPosition.value = 0L
                    }
                    is MusicStates.CurrentMediaItemIndex -> {
                        "MusicStates.CurrentMediaItemIndex:it.mediaItemIndex:${it.mediaItemIndex}".logd()
                        _mediaItemIndex.value = it.mediaItemIndex
                    }
                    else -> {}
                }
            }
        }
    }

    fun getLocalMusicList() {
        _isDataLoading.value = true
        viewModelScope.launch{
//            getLocalMusicListFromCache()
            var musicList = musicRepository.getMusics()
            "--musicList.size:${musicList.size}".logd()
            onUiEvent(MusicUiEvent.RefreshMessage(App.app.getString(R.string.get_music_success, musicList.size.toString())))
            if (musicList.isNotEmpty()){
//                AppCache.refreshCacheMusicList(gson.toJson(musicList))
                _musicListState.value = musicList
                setMusicItems()
            }
            _isDataLoading.value = false
        }
    }

    suspend fun getLocalMusicListFromCache() {
        val musicListJson = AppCache.cacheMusicList.first()
        if (musicListJson.isNotEmpty()) {
            // 初始化 Gson 时，通过 GsonBuilder 注册 UriTypeAdapter
            val typeToken = object : TypeToken<List<AudioItem>>(){}.type
            val musicList = gson.fromJson<List<AudioItem>>(musicListJson, typeToken)
            "缓存的音乐数量：${musicList.size}".logd()
            musicList.forEach { audioItem ->
                "bitmap:${audioItem.artWork == null}".logd()
            }
            _musicListState.value = musicList
            setMusicItems()
        }
    }

    fun setMusicItems(){
        musicListState.value.map { audioItem ->
            AudioItem.toMediaItem(audioItem)
        }.also {
            musicServiceHandler.setMediaItem(it)
        }
    }

    fun refreshAiImage(){
        viewModelScope.launch{
            _imageModel.value = generateImageUsecase()
            val result = "获取到的图片地址为: ${_imageModel.value.url}，errorMsg: ${_imageModel.value.errorMsg}，createTime: ${_imageModel.value.createTime}"
            result.logd()
            onUiEvent(MusicUiEvent.RefreshMessage(result))
        }
    }

    /**
     * 处理UI事件
     */
    fun onUiEvent(event: MusicUiEvent) {
        when(event){
            is MusicUiEvent.RefreshMessage -> {
//                "toastMsg:${event.msg}".logd()
                _toastMsg.value = event.msg
            }
            is MusicUiEvent.RefreshAiImage -> {
                "刷新AI图片".logd()
                refreshAiImage()
            }
            is MusicUiEvent.PlayPause -> {
                musicServiceHandler.onMediaStateEvent(MediaStateEvents.PlayPause)
            }
            is MusicUiEvent.Stop -> {
                musicServiceHandler.onMediaStateEvent(MediaStateEvents.Stop)
            }
            is MusicUiEvent.SeekTo -> {
                musicServiceHandler.onMediaStateEvent(MediaStateEvents.SeekTo, seekPosition = event.progress.toLong())
            }
            is MusicUiEvent.SeekToPrevious -> {
                musicServiceHandler.onMediaStateEvent(MediaStateEvents.SeekToPrevious)
            }
            is MusicUiEvent.SeekToNext -> {
                musicServiceHandler.onMediaStateEvent(MediaStateEvents.SeekToNext)
            }
            is MusicUiEvent.Backward -> {
                musicServiceHandler.onMediaStateEvent(MediaStateEvents.Backward)
            }
            is MusicUiEvent.Forward -> {
                musicServiceHandler.onMediaStateEvent(MediaStateEvents.Forward)
            }
            is MusicUiEvent.RefreshAutoNext -> {
                _autoNext.value = 0L
            }
            is MusicUiEvent.ReleasePlayer -> {
                musicServiceHandler.onMediaStateEvent(MediaStateEvents.Release)
            }
            is MusicUiEvent.SelectedMusicChange -> {
                _currentPosition.value = 0L
                musicServiceHandler.onMediaStateEvent(MediaStateEvents.SelectedMusicChange, selectMusicIndex = event.index)
            }
            is MusicUiEvent.MediaProgress -> {
                musicServiceHandler.onMediaStateEvent(MediaStateEvents.MediaProgress(event.progress))
            }
            else -> {}
        }
    }

    @SuppressLint("DefaultLocale")
    private fun formatDurationValue(duration: Long): String {
        val minutes = MINUTES.convert(duration, MILLISECONDS)
        val seconds = (minutes) - minutes * SECONDS.convert(1, MINUTES)

        return String.format("%02d:%02d", minutes, seconds)
    }

    override fun onCleared() {
        viewModelScope.launch{
            musicServiceHandler.onMediaStateEvent(MediaStateEvents.Stop)
        }
        super.onCleared()
    }

}